import querystring from "querystring";
import fs from 'fs/promises'
import {v4} from 'uuid'
import path from 'path'
const starts = {
  "application/x-www-form-urlencoded"(content) {
    return querystring.parse(content.toString());
  },
  "application/json"(content) {
    return JSON.parse(content.toString());
  },
};

Buffer.prototype.split = function (sep) {
  let headerLines = [];
  sep = Buffer.isBuffer(sep) ? sep : Buffer.from(sep);
  let offset = 0;
  let index = 0;
  while (-1 !== (index = this.indexOf(sep, offset))) {
    headerLines.push(this.slice(offset, index));
    offset = index + sep.length;
  } // str.indexOf(分隔符,查找的位置)
  headerLines.push(this.slice(offset)); // 分割后的最后一部分也放到数组里
  return headerLines;
};
async function formData(content, boundary, uploadDir) {
  let headerLines = content.split("--" + boundary);
  headerLines = headerLines.slice(1, -1);

  const result = {};
  await Promise.all(headerLines.map(async (line) => {
    let [head, ...content] = line.split("\r\n\r\n"); // type 和 内容之间是两个换行
    let contentType = head.toString();
    let name = contentType.match(/name="(.+?)"/)[1];
    if (contentType.includes("Content-Type")) {
      content = Buffer.concat(content).slice(0, -2);
      const filename = v4()
      await fs.writeFile(path.join(uploadDir, filename), content);
      let file = {
        originalFilename: contentType.match(/filename="(.+?)"/)[1],
        type: contentType.match(/Content-Type: ([^\r\n]+)/)[1],
        size: content.length,
        filename,
      };
      result[name] = (result[name] || []);
      result[name].push(file);
    } else {
      result[name] = Buffer.concat(content).toString().slice(0, -2);
    }
  }))
  return result
  
}
function bodyParser({ uploadDir }) {
  return async (ctx, next) => {
    // 解析请求体，将结果 给 赋值到ctx.request.body
    await new Promise((resolve, reject) => {
      const arr = [];
      ctx.req.on("data", function (chunk) {
        arr.push(chunk);
      });
      ctx.req.on("end", function (chunk) {
        let type = ctx.get("Content-Type");
        // 给上下文中的request自定一个body属性

        if (type) {
          const content = Buffer.concat(arr);
          if (type.includes("multipart/form-data")) {
            // 表单内容， 表单的分割符号
            formData(content, type.split("=")[1], uploadDir); // 将文件上传到某个目录中
            // 信息保存到 ctx.request.body
            ctx.request.body = {};
          } else {
            ctx.request.body = starts[type](content);
          }
        }

        resolve();
      });
    });
    return next();
  };
}

export default bodyParser;
